/**
 * 
 */
package cn.com.generaldata.os.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Map;

import org.springframework.core.io.ClassPathResource;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * @author acer
 * 
 */
public class XMLUtil {

	public static String marshalSimple(Object object) throws UnsupportComplexityException {
		if (object instanceof XMLComplexityIntf) {
			throw new UnsupportComplexityException();
		}

		XStream xs = new XStream();
		xs.processAnnotations(object.getClass());
		return xs.toXML(object);
	}

	@SuppressWarnings({ "rawtypes" })
	public static Object unmarshalSimple(String xml, Class clazz) {
		XStream xs = new XStream(new DomDriver());
		xs.processAnnotations(clazz);
		return xs.fromXML(xml);
	}

	@SuppressWarnings({ "rawtypes" })
	public static String marshalComplex(Object obj, XMLComplexityIntf complex) throws AliasMapNotFoundException {
		Map<String, Class> map = complex.generateAliasMap();
		if (null == map || map.isEmpty()) {
			throw new AliasMapNotFoundException();
		}
		XStream xs = new XStream();
		for (String alias : map.keySet()) {
			Class type = map.get(alias);
			xs.alias(alias, type);
		}
		return xs.toXML(obj);
	}

	@SuppressWarnings({ "rawtypes" })
	public static Object unmarshalComplex(String xml, XMLComplexityIntf complex) throws AliasMapNotFoundException {
		Map<String, Class> map = complex.generateAliasMap();
		if (null == map || map.isEmpty()) {
			throw new AliasMapNotFoundException();
		}
		XStream xs = new XStream(new DomDriver());
		for (String alias : map.keySet()) {
			Class type = map.get(alias);
			xs.alias(alias, type);
		}
		return xs.fromXML(xml);
	}

	@SuppressWarnings({ "rawtypes" })
	public static Object loadFromClassPathFile(String fileName, XMLComplexityIntf complex)
			throws AliasMapNotFoundException {
		Map<String, Class> map = complex.generateAliasMap();
		if (null == map || map.isEmpty()) {
			throw new AliasMapNotFoundException();
		}
		ClassPathResource resource = new ClassPathResource(fileName);
		InputStream is = null;
		InputStreamReader isr = null;
		try {
			File xmlFile = resource.getFile();
			if (!xmlFile.exists()) {
				return null;
			}
			XStream xs = new XStream(new DomDriver());
			for (String alias : map.keySet()) {
				Class type = map.get(alias);
				xs.alias(alias, type);
			}
			is = new FileInputStream(xmlFile);
			isr = new InputStreamReader(is, "UTF-8");
			return xs.fromXML(new FileInputStream(xmlFile));
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		} finally {
			try {
				if (isr != null) {
					isr.close();
				}
				if (is != null) {
					is.close();
				}
			} catch (Exception e) {
			}
		}
	}

	@SuppressWarnings({ "rawtypes" })
	public static Object loadFromXMLFile(String fileName, XMLComplexityIntf complex) throws AliasMapNotFoundException {
		Map<String, Class> map = complex.generateAliasMap();
		if (null == map || map.isEmpty()) {
			throw new AliasMapNotFoundException();
		}

		InputStream is = null;
		InputStreamReader isr = null;
		try {
			File xmlFile = new File(fileName);
			if (!xmlFile.exists()) {
				return null;
			}
			XStream xs = new XStream(new DomDriver());
			for (String alias : map.keySet()) {
				Class type = map.get(alias);
				xs.alias(alias, type);
			}

			is = new FileInputStream(xmlFile);
			isr = new InputStreamReader(is, "UTF-8");
			// isr = new InputStreamReader(is, "ASCII");

			int r = 0;
			String xml_des = "";
			while ((r = isr.read()) != -1) {

				xml_des = xml_des + (char) r;
			}
			xml_des = xml_des.substring(8, (xml_des.length() - 9));
			// System.out.println("PCI内容：" + xml_des);
			// System.out.println("PCI字节长度：" + xml_des.getBytes("UTF-8").length);

			// xml解密
			DESUtil desutil = new DESUtil();
			String xml = desutil.decrypt(xml_des);
			// System.out.println("Xml解密：" + xml);

			// String xml_des = (String) xs.fromXML(isr);
			// System.out.println(xml_des);
			// System.out.println("------------------");
			// System.out.println(xml);
			// Object obj = desutil.decrypt(xml_des);
			Object obj = xs.fromXML(xml);
			// Object obj = xs.fromXML(isr);
			return obj;
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		} finally {
			try {
				if (isr != null) {
					isr.close();
				}
				if (is != null) {
					is.close();
				}
			} catch (Exception e) {
			}
		}
	}

	@SuppressWarnings("rawtypes")
	public static void writeToXMLFile(Object object, String fileName, XMLComplexityIntf complex)
			throws AliasMapNotFoundException {
		Map<String, Class> map = complex.generateAliasMap();
		if (null == map || map.isEmpty()) {
			throw new AliasMapNotFoundException();
		}

		OutputStream os = null;
		OutputStreamWriter osw = null;
		try {
			File xmlFile = new File(fileName);
			XStream xs = new XStream(new DomDriver());
			for (String alias : map.keySet()) {
				Class type = map.get(alias);
				xs.alias(alias, type);
			}

			os = new FileOutputStream(xmlFile);
			osw = new OutputStreamWriter(os, "UTF-8");

			// xml加密
			String xml = xs.toXML(object);
			DESUtil desutil = new DESUtil();
			String xml_des = desutil.encrypt(xml);
			// System.out.println("xml信息：" + xml_des);
			// System.out.println("xml的长度：" + xml_des.getBytes("UTF-8").length);

			Object object_desEncrypt = xml_des;
			// System.out.println(xml);
			// System.out.println("----------------加密---------------------");
			// System.out.println(xml_des);
			// System.out.println("----------------解密--------------------");
			// System.out.println(desutil.decrypt(xml_des));

			xs.toXML(object_desEncrypt, osw);

			// 设置文件只读属性
			xmlFile.setReadOnly();
			// xs.toXML(object, osw);
		} catch (Exception ex) {
			ex.printStackTrace();
			return;
		} finally {
			try {
				if (osw != null) {
					osw.close();
				}
				if (os != null) {
					os.close();
				}
			} catch (Exception e) {
			}
		}
	}
}
